/*
 * Copyright 2009-2010 Belmont Software Services
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.belmont.backup.client;

import java.util.*;
import com.google.gwt.core.client.*;
import com.google.gwt.user.client.*;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.rpc.*;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.event.logical.shared.*;

public class ServiceOptionsPanel extends UIPanel {
    static final int ENABLE_SERVICE_INDEX = 0;
    static final int BACKUP_DIR_INDEX = 1;
    static final int SERVICE_PORT_INDEX = 2;
    static final int RESTART_INDEX = 3;
    static final int BRANDING_INDEX = 4;
    static final int PASSWORD_INDEX = 5;

    DialogBox confirmRestartDialog;
    DeckPanel serviceDeck = new DeckPanel();
    TextBox portField = new TextBox();
    TextBox backupDirectoryField = new TextBox();
    RadioButton serviceOn = new RadioButton("ServiceEnabled", "on");
    RadioButton serviceOff = new RadioButton("ServiceEnabled", "off");
    TextBox usernameField = new TextBox();
    PasswordTextBox passwordField = new PasswordTextBox();
    TextBox companyField = new TextBox();
    TextBox productField = new TextBox();
    TextBox logoField = new TextBox();
    TextBox clientField = new TextBox();
    TextBox urlField = new TextBox();

    public ServiceOptionsPanel(BackupUI main) {
        super(main, "Service Options");
    }

    public void refresh() {
        main.service.getBrandingStrings(new AsyncCallback<String[]>() {
                public void onFailure(Throwable caught) {
                    main.print("Failed to get branding strings, using default.");
                }
                public void onSuccess(String result[]) {
                    companyField.setText("Belmont");
                    productField.setText("Backup Server");
                    logoField.setText("/ui/Belmont.png");
                    if (result != null) {
                        if (result[BackupUI.BRANDING_COMPANY] != null) {
                            companyField.setText(result[BackupUI.BRANDING_COMPANY]);
                        }
                        if (result[BackupUI.BRANDING_PRODUCT] != null) {
                            productField.setText(result[BackupUI.BRANDING_PRODUCT]);
                        }
                        if (result[BackupUI.BRANDING_LOGO_URL] != null) {
                            logoField.setText(result[BackupUI.BRANDING_LOGO_URL]);
                        }
                        clientField.setText(result[BackupUI.BRANDING_CLIENT_NAME]);
                        urlField.setText(result[BackupUI.BRANDING_COMPANY_URL]);
                    }
                }
            });

        main.service.getAdminUser(new AsyncCallback<String[]>() {
                public void onFailure(Throwable caught) {
                    main.print("Error getting admin user");
                }
                public void onSuccess(String result[]) {
                    if (result != null && result.length == 2) {
                        usernameField.setText(result[0]);
                        passwordField.setText(result[1]);
                    }
                }
            });

        main.service.getServicePort(new AsyncCallback() {
                public void onFailure(Throwable caught) {
                    main.print("Communication with backup server failed.");
                }
                public void onSuccess(Object result) {
                    portField.setText((String)result);
                }
            });

        main.service.getBackupRoot(new AsyncCallback() {
                public void onFailure(Throwable caught) {
                    main.print("Communication with backup server failed.");
                }
                public void onSuccess(Object result) {
                    backupDirectoryField.setText((String)result);
                }
            });

        main.service.isServiceEnabled(new AsyncCallback<Boolean>() {
                public void onFailure(Throwable caught) {
                    main.print("Communication with backup server failed.");
                }
                public void onSuccess(Boolean result) {
                    serviceOn.setValue(result);
                    serviceOff.setValue(!result);
                }
            });
    }

    void setPort() {
        String v = portField.getText().trim();

        try {
            int p = Integer.parseInt(v);
            if (p <= 0) {
                main.print("Port must be greater than zero "+p);
                return;
            }
            main.service.setPort(p, new AsyncCallback() {
                    public void onSuccess(Object result) {
                        main.print("Changed service port");
                    }
                    public void onFailure(Throwable caught) {
                        main.print("Failed to change service port.");
                    }
                });
        } catch (NumberFormatException ex) {
            main.print("Port must be a valid number "+v);
        }
    }

    void createRestartDialog() {
        confirmRestartDialog = new DialogBox(false, true);
        confirmRestartDialog.setText("Confirm Restart");
        VerticalPanel vp = new VerticalPanel();
        vp.setSpacing(5);
        HorizontalPanel p1 = new HorizontalPanel();
        p1.setSpacing(5);
        p1.add(new Image(main.getBrandingProperty(BackupUI.BRANDING_LOGO_URL, "/ui/Belmont.png")));
        p1.add(new HTML("<b>Please confirm you want to restart the "+main.getBrandingProperty(BackupUI.BRANDING_PRODUCT,"Belmont Backup Server")+"</b>"));
        HorizontalPanel p = new HorizontalPanel();
        p.setSpacing(2);
        Button cancel = new Button("Cancel");
        Button ok = new Button("Ok");
        p.add(cancel);
        p.add(ok);
        ok.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    confirmRestartDialog.hide();
                    main.print("Restarting server...");
                    main.service.restart(10, new AsyncCallback() {
                            public void onSuccess(Object result) {
                                main.print("Restarted server: "+result);
                            }
                            public void onFailure(Throwable caught) {
                                main.print("Failed to restart server");
                            }
                        });
                }
            });
        cancel.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    confirmRestartDialog.hide();
                    main.print("Restart cancelled.");
                }
            });
        vp.add(p1);
        vp.add(p);
        confirmRestartDialog.setWidget(vp);
    }

    void restartService() {
        if (confirmRestartDialog == null) {
            createRestartDialog();
        }
        main.print("");
        confirmRestartDialog.showRelativeTo(serviceDeck);
    }

    void setBackupRoot() {
        String r = backupDirectoryField.getText().trim();

        if (r.length() == 0) {
            main.print("No directory specified.");
        } else {
            main.service.setBackupRoot(r, new AsyncCallback<String>() {
                    public void onSuccess(String result) {
                        main.print(result);
                    }
                    public void onFailure(Throwable caught) {
                        main.print("Failed to set backup root: "+caught.toString());
                    }
                });
        }
    }

    void setEnableService() {
        main.service.setEnableService(serviceOn.getValue(), new AsyncCallback() {
                public void onSuccess(Object result) {
                    if (serviceOn.getValue()) {
                        main.print("Service enabled");
                    } else {
                        main.print("Service disabled");
                    }
                }
                public void onFailure(Throwable caught) {
                    if (serviceOn.getValue()) {
                        main.print("Failed to enable service.");
                        serviceOn.setValue(false);
                    } else {
                        main.print("Failed to disable service.");
                        serviceOn.setValue(true);
                    }
                }
            });
    }

    void setBranding() {
        String s[] = new String[3];

        s[BackupUI.BRANDING_COMPANY] = companyField.getText();
        s[BackupUI.BRANDING_PRODUCT] = productField.getText();
        s[BackupUI.BRANDING_LOGO_URL] = logoField.getText();
        s[BackupUI.BRANDING_CLIENT_NAME] = clientField.getText();
        s[BackupUI.BRANDING_COMPANY_URL] = urlField.getText();

        main.service.setBrandingStrings(s, new AsyncCallback() {
                public void onSuccess(Object result) {
                    main.print("Branding updated.");
                }
                public void onFailure(Throwable caught) {
                    main.print("Failed to update branding.");
                }
            });
    }

    void setPassword() {
        String ups[] = new String[2];
        ups[0] = usernameField.getText();
        ups[1] = passwordField.getText();
        main.service.setAdminUser(ups, new AsyncCallback() {
                public void onSuccess(Object result) {
                    main.print("Admin user changed, will apply after restart.");
                }
                public void onFailure(Throwable caught) {
                    main.print("Failed to update admin user");
                }
            });
    }

    public void doApply() {
        int idx = serviceDeck.getVisibleWidget();

        switch (idx) {
            case ENABLE_SERVICE_INDEX:
                setEnableService();
                break;
            case BACKUP_DIR_INDEX:
                setBackupRoot();
                break;
            case SERVICE_PORT_INDEX:
                setPort();
                break;
            case RESTART_INDEX:
                restartService();
                break;
            case BRANDING_INDEX:
                setBranding();
                break;
            case PASSWORD_INDEX:
                setPassword();
                break;
            default:
                break;
        }
    }

    public Widget init() {
        DockPanel dp = new DockPanel();
        HTML help = new HTML("Configure global options for the backup service.");
        MenuBar menu = new MenuBar(true);

        createServiceEnablePanel("Enable/Disable Service", menu);
        menu.addSeparator();
        createBackupDirPanel("Set Backup Directory", menu);
        menu.addSeparator();
        createSetPortPanel("Set Service Port", menu);
        menu.addSeparator();
        createRestartPanel("Restart Server", menu);
        menu.addSeparator();
        createBrandingPanel("Branding Options", menu);
        menu.addSeparator();
        createPasswordPanel("Set Admin Password", menu);

        createTaskLayout("Service Tasks:", help, menu, dp, serviceDeck, true, true);

        return dp;

    }

    void createServiceEnablePanel(String menuTitle, MenuBar menu) {
        VerticalPanel vp = new VerticalPanel();
        HTML help = new HTML("Set whether to allow or disallow backup/restore operations for all hosts.");
        Grid g = new Grid(1,3);

        help.setStyleName("backup-Help-Task");
        vp.add(help);
        HorizontalPanel hp = new HorizontalPanel();
        hp.add(serviceOn);
        hp.add(serviceOff);
        addRowToControlPanel(g, 0,
                             "Enable/Disable Service:",
                             hp,
                             "Enable or disable backup and restore operations for all clients.");
        g.setWidth("100%");
        g.setCellPadding(4);
        vp.add(g);
        serviceDeck.add(vp);
	
        menu.addItem(menuTitle, true, new Command() {
                public void execute() {
                    cancelButton.setVisible(true);
                    serviceDeck.showWidget(ENABLE_SERVICE_INDEX);
                }
            });
    }

    void createBackupDirPanel(String menuTitle, MenuBar menu) {
        VerticalPanel vp = new VerticalPanel();
        HTML help = new HTML("Changes the directory used for backups. Note that this will not move the backups in the old directory to the new location. This change requires a server restart.");
        Grid g = new Grid(1,3);

        help.setStyleName("backup-Help-Task");
        vp.add(help);
        backupDirectoryField.setWidth("100%");
        backupDirectoryField.setVisibleLength(40);
        addRowToControlPanel(g, 0,
                             "Backup Directory:",
                             backupDirectoryField,
                             "Directory used by the service to store all the backed-up files.");
        g.setWidth("100%");
        g.setCellPadding(4);
        vp.add(g);
        serviceDeck.add(vp);

        menu.addItem(menuTitle, true, new Command() {
                public void execute() {
                    cancelButton.setVisible(true);
                    serviceDeck.showWidget(BACKUP_DIR_INDEX);
                }
            });
    }

    void createSetPortPanel(String menuTitle, MenuBar menu) {
        VerticalPanel vp = new VerticalPanel();
        HTML help = new HTML("Changes the port number for the backup server. Note that this may disable any working clients unless you have configured them to use the new port number. This change will only take effect after restarting the service.");
        Grid g = new Grid(1,3);

        help.setStyleName("backup-Help-Task");
        vp.add(help);
        portField.setVisibleLength(6);
        addRowToControlPanel(g, 0,
                             "Port:",
                             portField,
                             "Port number to use for the backup service.");
        g.setWidth("100%");
        g.setCellPadding(4);
        vp.add(g);
        serviceDeck.add(vp);

        menu.addItem(menuTitle, true, new Command() {
                public void execute() {
                    cancelButton.setVisible(true);
                    serviceDeck.showWidget(SERVICE_PORT_INDEX);
                }
            });
    }

    void createRestartPanel(String menuTitle, MenuBar menu) {
        VerticalPanel vp = new VerticalPanel();
        HTML help = new HTML("Choosing the Apply button below will restart the backup service. This is required if you made changes to the backup root or the service port before these changes take effect.");

        help.setStyleName("backup-Help-Task");
        vp.add(help);
        serviceDeck.add(vp);

        menu.addItem(menuTitle, true, new Command() {
                public void execute() {
                    cancelButton.setVisible(false);
                    serviceDeck.showWidget(RESTART_INDEX);
                }
            });
    }

    void createBrandingPanel(String menuTitle, MenuBar menu) {
        VerticalPanel vp = new VerticalPanel();
        HTML help = new HTML("This set of options allows you to customize the product name and logo.");	
        Grid g = new Grid(5,3);

        help.setStyleName("backup-Help-Task");
        vp.add(help);
        companyField.setVisibleLength(60);
        addRowToControlPanel(g, 0,
                             "Company Name:",
                             companyField,
                             "Company name to use for the backup service.");
        productField.setVisibleLength(60);
        addRowToControlPanel(g, 1,
                             "Product Name:",
                             productField,
                             "Product name to use for the backup service.");
        clientField.setVisibleLength(60);
        addRowToControlPanel(g, 2,
                             "Client Product Name:",
                             clientField,
                             "Product name to use for the backup service client.");
        urlField.setVisibleLength(60);
        addRowToControlPanel(g, 3,
                             "Company URL:",
                             urlField,
                             "Support URL to use in the backup service.");
        logoField.setVisibleLength(60);
        addRowToControlPanel(g, 4,
                             "Logo URL:",
                             logoField,
                             "URL to use for the logo for the product.");
        g.setWidth("100%");
        g.setCellPadding(4);
        vp.add(g);
        serviceDeck.add(vp);

        menu.addItem(menuTitle, true, new Command() {
                public void execute() {
                    serviceDeck.showWidget(BRANDING_INDEX);
                }
            });
    }

    void createPasswordPanel(String menuTitle, MenuBar menu) {
        VerticalPanel vp = new VerticalPanel();
        HTML help = new HTML("This set of options allows you to set the admin password for the service.");
        Grid g = new Grid(3,3);

        help.setStyleName("backup-Help-Task");
        vp.add(help);
        usernameField.setVisibleLength(30);
        addRowToControlPanel(g, 0,
                             "User:",
                             usernameField,
                             "Username to use for the admin login.");

        passwordField.setVisibleLength(30);
        addRowToControlPanel(g, 1,
                             "Password:",
                             passwordField,
                             "Password to use for the backup service.");
        g.setWidth("100%");
        g.setCellPadding(4);
        vp.add(g);
        serviceDeck.add(vp);

        menu.addItem(menuTitle, true, new Command() {
                public void execute() {
                    serviceDeck.showWidget(PASSWORD_INDEX);
                }
            });
    }
}